package _tema3;

import java.io.*;
import java.net.*;
import java.util.ArrayList;

public class Server {

	private ServerSocket server;
	private ArrayList<Persona> personas;
	private ArrayList<String> cargos;
	private DataInputStream archivo;
	
	final int PORT = 7900;
	final int COLA = 10;
	final int TIMEOUT = 60000;
	
	public Server() {
		try {
			System.out.println("Leyendo archivo...");
			this.leerArchivo();
			this.cerrarArchivo();
			this.server = new ServerSocket(this.PORT, this.COLA);
			this.server.setSoTimeout(this.TIMEOUT);
			System.out.println("Server abierto, esperando...");
			this.aceptarClientes();
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void aceptarClientes() {
		while (true) {
			try {
				System.out.println("Listo para atender nuevo cliente");
				InnerServer innerServer = new InnerServer(server.accept(), this.personas, this.cargos);
				innerServer.start();
			} catch (SocketTimeoutException e) {
				System.out.println("Timeout");
				break;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void leerArchivo() {
		try {
			String ruta = System.getProperty("user.dir") + "/Tareas.dat";
			this.archivo= new DataInputStream(new FileInputStream(ruta));
			
			this.personas = new ArrayList<Persona>();
			this.cargos = new ArrayList<String>();
			
			while (true) {
				Persona p = new Persona();
				p.setCargo(this.archivo.readUTF());
				p.setNombre(this.archivo.readUTF());
				this.personas.add(p);
				
				if (!this.cargos.contains(p.getCargo()))
					this.cargos.add(p.getCargo());
			}
		} catch (EOFException e) {
			System.out.println("Fin de lectura de archivo");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private void cerrarArchivo() {
		try {
			this.archivo.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//Main Server
	public static void main(String[] args) {
		new Server();
	}
	
	//Clase InnerServer
	class InnerServer extends Thread {
		
		private Socket socket;
		private ObjectOutputStream output;
		private ObjectInputStream input;
		
		private String nombreCliente;
		private ArrayList<Persona> personas;
		private ArrayList<String> cargos;
		
		public InnerServer(Socket s, ArrayList<Persona> personas, ArrayList<String> cargos) {
			this.socket = s;
			this.personas = personas;
			this.cargos = cargos;
		}
		
		public void run() {
			try {
				this.output = new ObjectOutputStream(this.socket.getOutputStream());
				this.input = new ObjectInputStream(this.socket.getInputStream());
				recibir();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		void recibir() {
			try {
				Mensaje m = (Mensaje)this.input.readObject();
				while (true) {
					switch (m.getTipo()) {
					case Mensaje.CONECTAR:
						this.nombreCliente = (String)m.getDato();
						System.out.println(this.nombreCliente + " conectado" );
						enviarCargos();
						break;
					case Mensaje.ENVIAR:
						String cargo = (String)m.getDato();
						System.out.println("Enviando Personas de cargo " + cargo + " a " + this.nombreCliente);
						enviarPersonas(cargo);
						break;
					case Mensaje.DESCONECTAR:
						desconectarCliente();
						System.out.println(this.nombreCliente + " desconectado");
						break;
					}
					if (!socket.isClosed())
						m = (Mensaje)this.input.readObject();
					else
						break;
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}

		void desconectarCliente() {
			if (!this.socket.isClosed()) {
				try {
					this.output.close();
					this.input.close();
					this.socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		void enviarPersonas(String cargo) {
			ArrayList<String> personasCargo = new ArrayList<String>();
			for (int i = 0; i < this.personas.size(); i++)
				if (this.personas.get(i).getCargo().equals(cargo))
					personasCargo.add(this.personas.get(i).getNombre());
			
			Mensaje m = new Mensaje();
			m.setTipo(Mensaje.ENVIAR);
			m.setDato(personasCargo);
			try {
				this.output.writeObject(m);
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}

		void enviarCargos() {
			Mensaje m = new Mensaje();
			m.setTipo(Mensaje.CONECTAR);
			m.setDato(this.cargos);
			try {
				this.output.writeObject(m);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}

}
